/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client;

import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @author caos
 */
public class CryptHelper {
    private PublicKey publicKey;
    private PublicKey remotePublicKey;
    private PrivateKey privateKey;
    private SecretKeySpec AESKey;
    
    CryptHelper()
    {
        try {
            KeyPairGenerator keyGenRSA = KeyPairGenerator.getInstance("RSA");
            keyGenRSA.initialize(1024);
            KeyPair keypair = keyGenRSA.genKeyPair();
            this.privateKey = keypair.getPrivate();
            this.publicKey = keypair.getPublic();
            
            KeyGenerator keyGenAES=KeyGenerator.getInstance("AES");
            keyGenAES.init(128);
             SecretKey skey = keyGenAES.generateKey();
             byte[] raw = skey.getEncoded();

            this.AESKey = new SecretKeySpec(raw, "AES");  
        } catch (NoSuchAlgorithmException ex) 
        {
            System.err.println("Error: "+ ex.getMessage());
        }
    }    
    
    void setRemotePK(byte[] remoteKey)
    {
        try
        {
            //System.out.println("Chiave rsa: " + (remoteKey));
            KeyFactory rsaKeyFac = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(remoteKey);  
            RSAPublicKey rsaPubKey = (RSAPublicKey)rsaKeyFac.generatePublic(keySpec);
            remotePublicKey=rsaPubKey; 
        } 
        catch (Exception ex) 
        {
            System.err.println("Error 59:CryptHelper: "+ ex.getMessage());
        }
    }
    byte[] getAESLocal()
    {
        return AESKey.getEncoded();
    }
    private static String asHex(byte[] src)
    {
        StringBuilder hexStr=new StringBuilder();
        for(byte b : src)
        {
            String tmp = Integer.toHexString(0xFF & b);
            if(tmp.length()==1)
                hexStr.append('0');
            hexStr.append(tmp);
        }
        return hexStr.toString();
    }    
    static String MD5(String toHash)
    {
        try
        {
            byte digest[]=MessageDigest.getInstance("MD5").digest(toHash.getBytes("UTF-8"));
            return asHex(digest);
        }
        catch(Exception ex)
        {
            return null;
        }
    }        
    
    static String RSAEncrypt(String toEncode, PublicKey destPublicKey)
    {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, destPublicKey);
            byte[] cipherData = cipher.doFinal(toEncode.getBytes());
            return  new sun.misc.BASE64Encoder().encode(cipherData);
        }
        catch(Exception ex)
        {
            return null;
        }
        
    }    
    String RSAEncryptLocal(String toEncode)
    {
        return RSAEncrypt(toEncode, publicKey);
    }    
    
    String RSAEncryptRemote(String toEncode)
    {
        return RSAEncrypt(toEncode, remotePublicKey);
    }    
    String RSADecryptLocal(String encodedMessage)
    {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] cipherData = cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(encodedMessage));
            return new String(cipherData);
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
            return null;
        }
    }    
    
    String AESEncryptLocal(String toEncode)
    {
        return AESEncrypt(toEncode, AESKey);
    }
    static String AESEncrypt(String toEncode, SecretKeySpec AESDestKey)
    {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, AESDestKey);
            byte[] cipherData = cipher.doFinal(toEncode.getBytes());
            return new sun.misc.BASE64Encoder().encode(cipherData);
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
            return null;
        }
    }
    
    static String AESDecrypt(String toDecode, SecretKeySpec AESDestKey)
    {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, AESDestKey);
            byte[] original = cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(toDecode));
            return new String(original);
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
            return null;
        }
    }
    
    String AESDecryptLocal(String toDecode)
    {
        return AESDecrypt(toDecode, AESKey);
    }
    
}
